﻿#include "udpinterface.h"
#include <QFile>
#include <QByteArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDebug>
#include <QtEndian>
#include <QThread>
#include <QNetworkDatagram>
#include <QDataStream>


using namespace Hydra_UDP;

UdpInterface::UdpInterface(QObject *parent) : QObject(parent)
{
    pSocket = new QUdpSocket(this);

    connect(pSocket, &QUdpSocket::aboutToClose, &mTimer, &QTimer::stop);

    init();
}




// 绑定网络
bool UdpInterface::bindNet(QString ip, quint16 port)
{

    return pSocket->bind(QHostAddress(ip), port, QUdpSocket::ShareAddress);

}


// 设置通信周期
void UdpInterface::setCommunicationCycle(quint16 value)
{
    mTimer.setInterval(value);
}

bool UdpInterface::setRemoteObject(QString ip, quint16 port)
{
    QHostAddress test;
    if (!test.setAddress(ip)) return false;

    remoteIp = ip;
    remotePort = port;

    return true;
}

void UdpInterface::setMsgData(QByteArray bytes)
{
    msgData = bytes;
}




// 接口初始化
void UdpInterface::init()
{
    // 定期发送数据给ATP
    connect(&mTimer, &QTimer::timeout, this, &UdpInterface::sendMsg);

    mTimer.start(DEFAULT_INTERVAL);
}



// CRC8计算
quint8 UdpInterface::calCRC8(QByteArray bytes, quint8 poly)
{
    quint8 tCRC = 0x00;
    quint8 tData = 0x00;

    quint32 tLen = bytes.length();
    quint32 tPos = 0;

    do {
        tData = bytes.mid(tPos, 1).toHex().toUInt(NULL, 16);
        ++tPos;

        tCRC ^= tData;

        for (int i = 0; i < 8; ++i) {
            if (tCRC & 0x80) {
                tCRC = (tCRC << 1) ^ poly;
            }
            else {
                tCRC = tCRC << 1;
            }
        }
    }while(--tLen);
    return tCRC;
}




// 通过查表计算CRC8
quint8 UdpInterface::calCRC8FromCRC8Table(QByteArray bytes)
{
    quint8 tCRC = 0x00;
    quint8 tData = 0x00;

    quint32 tLen = bytes.length();
    quint32 tPos = 0;

    do {
        tData = bytes.mid(tPos, 1).toHex().toUInt(NULL, 16);
        ++tPos;

        tCRC = crc8_table[tCRC ^ tData];
    }while(--tLen);
    return tCRC;
}


// 通过传入指针的形式，查表计算CRC16
quint16 UdpInterface::calCRC16FromCRC16Table(unsigned char *buf, int len)
{
    int counter;
    unsigned char *p=buf;
    unsigned short crc = 0x0000;
    for( counter = 0; counter < len; ++counter)
        crc = (crc<<8) ^ crc16_table[((crc>>8) ^ ++*(char *)p)&0x00FF];
    return crc;
}

// 通过传入字节数组的形式，查表计算CRC16-XMODEM
quint16 UdpInterface::calCRC16FromCRC16Table(QByteArray bytes)
{
    quint16 crc = 0x0000; // 初始值为0x0000

    for (int i = 0; i < bytes.size(); ++i) {
        crc = (crc << 8) ^ crc16_table[(crc >> 8) ^ (quint8)bytes.at(i)];
    }

    return crc;
}


// 通过传入字节数组的形式，查表计算CRC32
quint32 UdpInterface::calCRC32FromCRC32Table(QByteArray bytes) {
    quint32 crc = 0xFFFFFFFF;

    for (int i = 0; i < bytes.size(); ++i) {
        crc = (crc >> 8) ^ crc32_table[(crc ^ bytes.at(i)) & 0xFF];
    }

    return crc ^ 0xFFFFFFFF;
}


// 处理发送数据报文头
void UdpInterface::addTRDPHeader(QByteArray *pByte)
{
    SEND_HEADER tSendHeader;

    pByte->append(reinterpret_cast<char*>(&tSendHeader), sizeof(tSendHeader));

}


// 生成发送数据
void UdpInterface::addSendMsgData(QByteArray *pByte)
{
    QByteArray data;
    QString newString = msgData.replace(u8" ", "");

    for (int var = 0; var < newString.length() / 2; ++var) {
        bool ok;
        QString temp = newString.midRef(var * 2, 2).toString();

        ushort value = temp.toUShort(&ok, 16);

        if (ok) {
            data.append(value);
        }
    }

    *pByte+= data;

}

void UdpInterface::addCRC32(QByteArray *pByte, quint8 n)
{
    QByteArray data = pByte->mid(n, pByte->length() - n);

    quint32 value = calCRC32FromCRC32Table(data);
    quint32 reversedValue = qToBigEndian(value);
    pByte->append(reinterpret_cast<const char*>(&reversedValue), sizeof(reversedValue));

}


// 添加TRDP协议CRC16
void UdpInterface::addTRDPCRC16(QByteArray *pByte)
{
    QByteArray temp = pByte->mid(4, pByte->length() - 4);

    quint16 tCRC = qToBigEndian(calCRC16FromCRC16Table(temp));

    pByte->append(reinterpret_cast<char *>(&tCRC), sizeof(tCRC));
}

void UdpInterface::setHeaderLen(quint32 len)
{
    mHeaderLen = len;
}

void UdpInterface::stopSend()
{
    pSocket->close();
    delete pSocket;

}



// 获取数据
void UdpInterface::processReceivedMsg()
{
    while(pSocket->hasPendingDatagrams()) {

    }
}

void UdpInterface::sendMsg()
{
    QByteArray* tByte = new QByteArray;

//    addTRDPHeader(tByte);

    addSendMsgData(tByte);

    addCRC32(tByte, mHeaderLen);

    addTRDPCRC16(tByte);

    pSocket->writeDatagram(*tByte, QHostAddress(remoteIp), remotePort);

    if(tByte) {
        delete tByte;
        tByte = nullptr;
    }

}




